# -*- coding:utf-8 -*-
# created on 2017/01/05

from mathsolver.functions.base import *
from sympy.abc import x
from sympy import cos, Abs, Mul, Add, Pow, pi, sqrt, Integer, S, symbols


# 在三角形中，已知一些边和一些角的值，然后求另一条边或者几条边作为向量运算的结果
class XiangLiangTriCompute001(BaseFunction):
    def solver(self, *args):
        sides = args[0]
        angle = args[1]
        target = args[4]
        # 将边的值保存在字典sv里
        sv = {}
        for s in sides:
            if str(s[0]) in ['a', 'line(BC)', 'line(CB)', 'BC', 'CB']:
                sv['BC'], sv['CB'] = s[1], s[1]
            elif str(s[0]) in ['b', 'line(AC)', 'line(CA)', 'AC', 'CA']:
                sv['AC'], sv['CA'] = s[1], s[1]
            elif str(s[0]) in ['c', 'line(AB)', 'line(BA)', 'AB', 'BA']:
                sv['AB'], sv['BA'] = s[1], s[1]
        # 将角的值保存在字典av里
        av = {}
        if angle:
            for a in angle:
                av[a[0]] = a[1]
        # target = sympify(args[0].value)
        # 判断目标是求模长还是点积运算
        if isinstance(target, Mul) or isinstance(target, Add):
            output = target.expand()
        elif isinstance(target, Abs):
            output = target.args[0] ** 2
            output = output.expand()
        else:
            raise Exception("to do")
        res = 0
        # 展开后的output是形如n1*a^2+n2*b^2+n3*a*b的形式
        co = output.as_coefficients_dict()
        for c in co:
            # 参数是a^2的形式
            if isinstance(c, Pow):
                p = str(c.args[0].args[0])
                res = res + sv[p] ** 2 * co[c]
            # 参数是a*b的形式
            elif isinstance(c, Mul):
                p1 = str(c.args[0].args[0])
                p2 = str(c.args[1].args[0])
                sign = -1 if p1[0] == p2[1] or p1[1] == p2[0] else 1  # 判断夹角是锐角还是钝角
                # 找到夹角是哪个角
                for s in p1:
                    if s in p2:
                        the_angle = s
                # 找到夹角对应的边
                for i in ['AB', 'AC', 'BC']:
                    if the_angle not in i:
                        p3 = i
                if the_angle in av:
                    angle = av[the_angle]
                    cos_angle = cos(pi * angle / 180) if isinstance(angle, Integer) else cos(angle)
                else:
                    cos_angle = (sv[p1] ** 2 + sv[p2] ** 2 - sv[p3] ** 2) / (2 * sv[p1] * sv[p2])
                res = res + sv[p1] * sv[p2] * cos_angle * sign * co[c]
        res = sqrt(res) if isinstance(target, Abs) else res

        self.output.append(BaseValue(res))
        return self


# 在三角形中，已知两条边的值和两条边的向量运算，然后求另一条边的值
class XiangLiangTriCompute002(BaseFunction):
    def solver(self, *args):
        sides = args[0]
        abs_ = args[2]
        arith = args[3]
        target = args[4]
        t = target.args[0]
        sv = {str(t.args[0]): x, str(t.args[0])[::-1]: x}
        for s in sides:
            if str(s[0]) in ['a', 'line(BC)', 'line(CB)', 'BC', 'CB']:
                sv['BC'], sv['CB'] = s[1], s[1]
            elif str(s[0]) in ['b', 'line(AC)', 'line(CA)', 'AC', 'CA']:
                sv['AC'], sv['CA'] = s[1], s[1]
            elif str(s[0]) in ['c', 'line(AB)', 'line(BA)', 'AB', 'BA']:
                sv['AB'], sv['BA'] = s[1], s[1]
        if abs_:
            output = abs_[0][0].args[0] ** 2 - abs_[0][1] ** 2
            output = output.expand()
        elif arith:
            output = arith[0][0] - arith[0][1]
            output = output.expand()
        else:
            raise Exception("to do")
        co = output.as_coefficients_dict()
        eq1 = S.Zero
        cos_angle = symbols('cos_angle')
        for c in co:
            # 参数是a^2的形式
            if isinstance(c, Pow):
                p = str(c.args[0].args[0])
                eq1 = eq1 + sv[p] ** 2 * co[c]
            # 参数是a*b的形式
            elif isinstance(c, Mul):
                p1 = str(c.args[0].args[0])
                p2 = str(c.args[1].args[0])
                for s in p1:
                    if s in p2:
                        the_angle = s
                for i in ['AB', 'AC', 'BC']:
                    if the_angle not in i:
                        p3 = i
                sign = -1 if p1[0] == p2[1] or p1[1] == p2[0] else 1  # 判断夹角是锐角还是钝角
                eq1 = eq1 + sv[p1] * sv[p2] * cos_angle * sign * co[c]
                eq2 = sv[p1] ** 2 + sv[p2] ** 2 - sv[p3] ** 2 - 2 * sv[p1] * sv[p2] * cos_angle
            else:
                eq1 = eq1 + co[c]

        res = solve([eq1, eq2], [x, cos_angle])
        for r in res:
            if r[0] > 0 and r[1] > 0:
                res_x = r[0]
        self.output.append(BaseValue(res_x))
        return self


class XiangLiangTriCompute(BaseFunction):
    cls = [XiangLiangTriCompute001, XiangLiangTriCompute002]

    def solver(self, *args):
        r = None
        sides = self.search('sides')
        angle = self.search('angle')
        abs_ = self.search('Abs')
        arith = self.search('Arith')
        target = sympify(args[0].value)
        for cl in XiangLiangTriCompute.cls:
            try:
                r = cl(verbose=True).solver(sides, angle, abs_, arith, target)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r
